<template>
  <div class="code-editor">
    <div class="top-tabs">
      <el-tabs v-model="editableTabsValue" type="card" closable class="file-tabs" @edit="handleTabsEdit">
        <el-tab-pane v-for="item in editableTabs" :key="item.path" :label="item.title" :name="item.path">
          <div class="editor">
            <v-ace-editor
              v-model:value="item.content"
              @init="editorInit"
              :lang="activeLang"
              :options="{
                enableBasicAutocompletion: true,
                enableSnippets: true,
                enableLiveAutocompletion: true,
                fontSize: 14,
                tabSize: 4,
                showPrintMargin: false,
                highlightActiveLine: true,
              }"
              theme="crimson_editor"
              style="height: 650px; width: 100%;"
            />
          </div>
        </el-tab-pane>
      </el-tabs>
    </div>
    <div class="show-info" id="show-info-div">
      <div @mousedown="dragShowHeight" class="show-info-resize"></div>
      <div class="operation">
        <div class="left">
          <div>日志</div>
        </div>
        <div class="right" v-show="closeVisible">
          <div class="open-dialog" @click="showInputVisible">输入</div>
          <div class="delete" @click="clearAll">
            <el-tooltip class="box-item" effect="light" content="清空" placement="top-end">
              <el-icon :size="15"><Delete /></el-icon>
            </el-tooltip>
          </div>
          <div class="close" @click="closeShowInfo">
            <el-tooltip class="box-item" effect="light" content="关闭" placement="top-end">
              <el-icon :size="18"><Close /></el-icon>
            </el-tooltip>
          </div>
        </div>
      </div>
      <div class="show-content" id="show-content">
        <p class="item-content" v-for="(item, idx) in logInfo" :key="idx">{{item}}</p>
      </div>
    </div>
  </div>
</template>

<script>
import { ElMessage } from 'element-plus'

import { defineComponent, ref, reactive, toRefs, onMounted, nextTick, watch } from "vue"
import * as ace from 'ace-builds'
ace.config.set('basePath', '/static/src-min-noconflict/')

import { VAceEditor } from "vue3-ace-editor"

import bus from '../../../config/bus'

import { save } from "@/api/index"

// declare var require: any

export default defineComponent({
  name: "code-editor",

  components: {
    VAceEditor
  },

  setup(props, { emit }) {
    const activeLang = ref('java')

    const editableTabsValue = ref('')
    const editableTabs = ref([])

    let logDiv = null
    //运行日志
    const logInfo = reactive([])

    //关闭按钮是否显示
    const closeVisible = ref(true)

    //得到file-tree组件传过来的值
    bus.on('showCode', e => {
      //判断，如果editableTabs已经存在当前标签，则打开当前标签，不予添加
      const newTabPath = e.info.data.path
      let flag = false
      for (let i = 0; i < editableTabs.value.length; i++) {
        let item = editableTabs.value[i]
        if (item.path == newTabPath) {
          flag = true
          break
        }
      }
      if (flag) {
        editableTabsValue.value = newTabPath
        return
      }
      editableTabs.value.push({
        title: e.info.data.name,
        path: e.info.data.path,
        content: e.code,
      })
      editableTabsValue.value = newTabPath
    })

    //创建的文件默认打开并激活
    bus.on('addAndOpen', e => addTabAndActive(e))

    //删除tab
    bus.on('deleteTabs', e => handleTabsEdit(e.path, 'remove'))

    //清空tabs
    bus.on('clearTabs', e => {
      editableTabs.value = []
      editableTabsValue.value = ''
    })

    //添加tab并将最新tab设置为激活状态
    const addTabAndActive = tab => {
      editableTabs.value.push({
        title: tab.name,
        path: tab.path,
        content: tab.code
      })
      editableTabsValue.value = tab.path
    }

    //监视激活文件的路径，根据路径改变语言支持
    watch(editableTabsValue, val => {
      let extension = val.substring(val.lastIndexOf('.') + 1)
      if (extension == 'yaml') {
        extension = 'yml'
      }
      activeLang.value = extension
    })

    //清空打印的日志
    const clearAll = () => logInfo.length = 0

    const state = reactive({ test: '' })

    //处理el-tab的操作
    const handleTabsEdit = (targetPath, action) => {
      if (action === 'remove') {
        const tabs = editableTabs.value
        let activePath = editableTabsValue.value
        if (activePath === targetPath) {
          tabs.forEach((tab, index) => {
            if (tab.path === targetPath) {
              const nextTab = tabs[index + 1] || tabs[index - 1]
              if (nextTab) {
                activePath = nextTab.path
              }
            }
          })
        }

        editableTabsValue.value = activePath
        editableTabs.value = tabs.filter((tab) => tab.path !== targetPath)
      }
    }

    //新增日志
    const appendLogs = log => {
      logInfo.push(log)
      logDiv.scrollTop = logDiv.scrollHeight
    }

    //显示输入框
    const showInputVisible = () => emit('showInputVisible')

    const editorInit = () => {
      require("ace-builds/src-noconflict/ext-language_tools")
      require("ace-builds/src-noconflict/snippets/sql")
      require("ace-builds/src-noconflict/theme-monokai")

      require("ace-builds/src-noconflict/mode-java")
      require("ace-builds/src-noconflict/mode-xml")
      require("ace-builds/src-noconflict/mode-html")
      require("ace-builds/src-noconflict/mode-yaml")
      require("ace-builds/src-noconflict/mode-properties")
      require("ace-builds/src-noconflict/mode-javascript")
      require("ace-builds/src-noconflict/mode-json")
      require("ace-builds/src-noconflict/mode-jsp")


      require("ace-builds/src-noconflict/snippets/less")
      require("ace-builds/src-noconflict/theme-chrome")
      require("ace-builds/src-noconflict/theme-ambiance")
      require("ace-builds/src-noconflict/theme-chaos")

      require("ace-builds/src-noconflict/theme-cloud9_day")//
      require("ace-builds/src-noconflict/theme-crimson_editor")//
      require("ace-builds/src-noconflict/theme-dreamweaver")//
      
      require("ace-builds/src-noconflict/ext-static_highlight")
      require("ace-builds/src-noconflict/ext-beautify")
    }

    //得到当前打开文件的路径
    const getOpenFile = () => {
      if (editableTabs.value.length == 0) return null
      return editableTabsValue.value
    }
    
    onMounted(() => {
      nextTick(() => {
        editorInit
      })
      logDiv = document.getElementById('show-content')
    })
    
    //监听ctrl+s保存快捷键
    document.onkeydown = (e) => {
      if ((e.ctrlKey || e.metaKey) && (e.key === 's' || e.key === 'S')) {
        //阻止默认事件
        e.preventDefault()
        //找到当前激活的tab，获取相关信息，执行save方法
        for (let i = 0; i < editableTabs.value.length; i++) {
          if (editableTabsValue.value == editableTabs.value[i].path) {
            console.log(editableTabs.value[i])
            save(editableTabs.value[i].path, editableTabs.value[i].content).then(res => {
              if (res.code === 0) {
                ElMessage('保存成功')
              } else {
                ElMessage.error(res.msg)
              }
            })
            break
          }
        }
      }
    }

    //拖动改变展示信息的高度
    const dragShowHeight = e => {
      let targetDiv = document.getElementById('show-info-div')
      //得到点击时该地图容器的宽高
      let targetDivHeight = targetDiv.offsetHeight
      let startX = e.clientX
      let startY = e.clientY
      document.onmousemove = e => {
        e.preventDefault()
        //得到鼠标拖动的宽高距离：取绝对值
        // let distX = Math.abs(e.clientX - startX)
        let distY = Math.abs(e.clientY - startY)
        //往上方拖动
        if (e.clientY < startY) {
          closeVisible.value = true
          targetDiv.style.height = targetDivHeight + distY + 'px'
        }
        //往下方拖动
        if (e.clientX < startX && e.clientY > startY) {
          targetDiv.style.height = (targetDivHeight - distY) + 'px'
        }
        if (parseInt(targetDiv.style.height) >= 300) {
          targetDiv.style.height = 300 + 'px'
        }
        if (parseInt(targetDiv.style.height) <= 50) {
          targetDiv.style.height = 50 + 'px'
        }
      }
      document.onmouseup = () => document.onmousemove = null
    }

    //关闭信息框
    const closeShowInfo = () => {
      let targetDiv = document.getElementById('show-info-div')
      targetDiv.style.height = 50 + 'px'
      closeVisible.value = false
    }

    return {
      ...toRefs(state),
      editorInit,
      dragShowHeight,
      closeShowInfo,
      closeVisible,
      logInfo,
      clearAll,
      getOpenFile,
      showInputVisible,
      appendLogs,
      editableTabsValue,
      handleTabsEdit,
      editableTabs,
      activeLang,
      addTabAndActive
    }
  },
})
</script>

<style lang="scss">
.code-editor {
  width: 100%;
  height: 100%;
  position: relative;

  .top-tabs {
    .file-tabs > .el-tabs__header {
      margin: 0;
    }
  }

  .show-info {
    position: absolute;
    bottom: 0;
    z-index: 100;
    width: 100%;
    height: 200px;
    color: #212B3E;

    .show-info-resize {
      position: absolute;
      right: 1px;
      top: 1px;
      width: 100%;
      height: 3px;
      cursor: row-resize;
    }

    .show-info-resize:hover {
      background-color: #666;
    }

    .show-content {
      width: 100%;
      height: 300px;
      overflow: auto;
      background-color: #FEFEFE;

      .item-content {
        padding-left: 10px;
        font-size: 12px;
      }

      .item-content:last-child {
        margin-bottom: 40px;
      }
    }

    .operation {
      display: flex;
      justify-content: space-between;
      background-color: #F2F2F2;
      border: 1px solid #DCDCDC;
      border-left: none;
      border-right: none;

      .left {
        display: flex;
      }

      .right {
        display: flex;

        .open-dialog {
          margin-right: 10px;
          cursor: pointer;
        }

        .open-dialog:hover {
          color: #5200FF;
        }

        .delete {
          margin-right: 10px;
        }

        .delete, .close {
          cursor: pointer;
          width: 18px;
          height: 18px;
          text-align: center;
          line-height: 18px;
          padding-top: 1px;
        }

        .delete:hover, .close:hover {
          background-color: #E6E6E8;
        }
      }
    }
  }
}

/* 修改光标颜色 */
.ace_cursor {
  color: black !important;
}
</style>